package com.ds.esd.bpm.custom.service;


import com.ds.bpm.client.*;
import com.ds.bpm.client.data.DataMap;
import com.ds.bpm.client.data.FormData;
import com.ds.bpm.engine.BPMException;
import com.ds.bpm.engine.WorkflowClientService;
import com.ds.bpm.enums.activitydef.ActivityDefPerformSequence;
import com.ds.bpm.enums.activitydef.ActivityDefPerformtype;
import com.ds.bpm.enums.right.PerformGroupEnums;
import com.ds.bpm.enums.right.RightCtx;
import com.ds.common.util.StringUtility;
import com.ds.config.ErrorResultModel;
import com.ds.config.ListResultModel;
import com.ds.config.ResultModel;
import com.ds.config.TreeListResultModel;
import com.ds.enums.db.MethodChinaName;
import com.ds.esd.bpm.custom.perform.WebPerformPerson;
import com.ds.esd.bpm.custom.plugins.right.NextActivityTree;
import com.ds.esd.bpm.custom.plugins.svgview.SVGProcessInstView;
import com.ds.esd.custom.annotation.DialogAnnotation;
import com.ds.esd.custom.api.annotation.APIEventAnnotation;
import com.ds.esd.custom.api.enums.CustomCallBack;
import com.ds.esd.custom.api.enums.RequestPathEnum;
import com.ds.esd.custom.enums.CustomMenuItem;
import com.ds.esd.custom.module.annotation.DynLoadAnnotation;
import com.ds.esd.custom.module.annotation.ModuleAnnotation;
import com.ds.esd.custom.nav.annotation.NavTabsViewAnnotation;
import com.ds.esd.custom.toolbar.MenuBarMenu;
import com.ds.esd.custom.toolbar.bpm.RouteCustomMenu;
import com.ds.esd.editor.enums.CustomMenuType;
import com.ds.esd.util.TabPageUtil;
import com.ds.jds.core.esb.EsbUtil;
import com.ds.org.Person;
import com.ds.web.annotation.Aggregation;
import com.ds.web.annotation.AggregationType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.*;

@Controller
@RequestMapping("/bpm/custom/")
@MethodChinaName(cname = "发送动作")
@MenuBarMenu(menuType = CustomMenuType.bpm, dynLoad = true)
@Aggregation(type = AggregationType.menu, sourceClass = PerformServiceImpl.class)
public class PerformServiceImpl {

    @MethodChinaName(cname = "退回上一步")
    @RequestMapping(method = RequestMethod.POST, value = "RouteBack")
    @RouteCustomMenu(routeType = {RouteToType.RouteBack})
    @APIEventAnnotation(callback = CustomCallBack.Reload, customRequestData = RequestPathEnum.ctx)
    public @ResponseBody
    ResultModel<Boolean> routeBack(String activityInstHistoryId, String activityInstId) {
        ResultModel resultModel = new ResultModel();
        try {
            if (activityInstHistoryId == null) {
                ActivityInst inst = this.getClient().getActivityInst(activityInstId);
                activityInstHistoryId = inst.getRouteBackActivityHistoryInstList().get(0).getActivityHistoryId();
            }
            this.getClient().routeBack(activityInstId, activityInstHistoryId, null);
        } catch (BPMException e) {
            resultModel = new ErrorResultModel();
        }
        return resultModel;
    }

    @MethodChinaName(cname = "收回")
    @RequestMapping(method = RequestMethod.POST, value = "TackBack")
    @RouteCustomMenu(routeType = {RouteToType.TackBack})
    @APIEventAnnotation(callback = CustomCallBack.Reload, customRequestData = RequestPathEnum.ctx)
    public @ResponseBody
    ResultModel<Boolean> tackBack(String activityInstId) {
        ResultModel resultModel = new ResultModel();
        try {
            this.getClient().takeBack(activityInstId, null);
        } catch (BPMException e) {
            resultModel = new ErrorResultModel();
        }
        return resultModel;
    }


    @RequestMapping(method = RequestMethod.POST, value = "SelectPerson")
    @NavTabsViewAnnotation(saveUrl = "bpm.custom.RouteTo")
    @ModuleAnnotation(caption = "选择人员", width = "400", dynLoad = true)
    @RouteCustomMenu(routeType = {RouteToType.SelectPersons})
    @DialogAnnotation
    @APIEventAnnotation(customRequestData = RequestPathEnum.ctx, isAllform = true)
    @ResponseBody
    public ListResultModel<List<NextActivityTree>> getSelectPerson(String activityInstId, String nextActivityDefId, RouteToType action) {
        ListResultModel<List<NextActivityTree>> performTree = new ListResultModel<>();
        if (nextActivityDefId != null) {
            performTree = TabPageUtil.getTabList(Arrays.asList(PerformGroupEnums.values()), NextActivityTree.class);
        }

        return performTree;

    }


    @RequestMapping(method = RequestMethod.POST, value = "MultiSelect")
    @NavTabsViewAnnotation(saveUrl = "bpm.custom.MultiRouteto")
    @ModuleAnnotation(caption = "发送",
            width = "400", dynLoad = true)
    @DialogAnnotation
    @RouteCustomMenu(routeType = {RouteToType.MultiSelect})
    @APIEventAnnotation(customRequestData = RequestPathEnum.ctx, isAllform = true)
    @ResponseBody
    public TreeListResultModel<List<NextActivityTree>> multiSelect(String activityInstId, RouteToType action) {
        TreeListResultModel<List<NextActivityTree>> performTree = new TreeListResultModel<>();

        try {
            if (activityInstId != null && !activityInstId.equals("")) {
                ActivityInst inst = this.getClient().getActivityInst(activityInstId);
                List<RouteDef> routeDefs = inst.getNextRoutes();
                List<ActivityDef> activityDefs = new ArrayList<>();
                for (RouteDef routeDef : routeDefs) {
                    ActivityDef activityDef = this.getClient().getActivityDef(routeDef.getToActivityDefId());
                    activityDefs.add(activityDef);
                }
                performTree=     TabPageUtil.getTabList(activityDefs, NextActivityTree.class);
            }
        } catch (BPMException e) {
            e.printStackTrace();
        }
        return performTree;

    }


    @MethodChinaName(cname = "重新发送")
    @RequestMapping(method = RequestMethod.POST, value = "ReSend")
    @RouteCustomMenu(routeType = {RouteToType.ReSend})
    @APIEventAnnotation(customRequestData = RequestPathEnum.ctx)
    public @ResponseBody
    ResultModel<Boolean> reSend(String activityInstHistoryId, String activityInstId) {
        ResultModel resultModel = new ResultModel();
        try {
            List<Map<RightCtx, Object>> ctxs = new ArrayList<Map<RightCtx, Object>>();
            List<String> activityDefIds = new ArrayList<String>();
            ActivityInst activityInst = this.getClient().getActivityInst(activityInstId);
            if ((activityInstHistoryId == null || activityInstHistoryId.equals("")) && (this.getClient().getLastActivityInstHistoryListByActvityInst(activityInstId, null).size() > 0)) {
                ActivityInstHistory activityInstHistory = this.getClient().getLastActivityInstHistoryListByActvityInst(activityInstId, null).get(0);
                activityInstHistoryId = activityInstHistory.getActivityHistoryId();
            }
            if (activityInstHistoryId == null && (this.getClient().getLastActivityInstHistoryListByActvityInst(activityInstId, null).size() > 0)) {
                ActivityInst hisactivityInst = this.getClient().copyActivityInstByHistory(activityInstHistoryId, null);
                RouteBean hisrouteBean = new RouteBean();
                hisrouteBean.getPerforms().setPerforms(this.getClient().getConnectInfo().getUserID());
                hisrouteBean.setNextActivityDefId(hisactivityInst.getActivityDefId());
                hisrouteBean.setActivityInstId(hisactivityInst.getActivityInstId());
                activityDefIds.add(hisactivityInst.getActivityDefId());
                ctxs.add(this.fillCtx(hisrouteBean));
            } else {
                RouteBean hisrouteBean = new RouteBean();
                hisrouteBean.getPerforms().setPerforms(this.getClient().getConnectInfo().getUserID());
                hisrouteBean.setNextActivityDefId(activityInst.getActivityDefId());
                hisrouteBean.setAction(RouteToType.RouteTo);
                hisrouteBean.setActivityInstId(activityInst.getActivityInstId());
                activityDefIds.add(activityInst.getActivityDefId());
                ctxs.add(this.fillCtx(hisrouteBean));
            }
            getClient().routeTo(activityInstId, activityDefIds, ctxs);

        } catch (BPMException e) {
            resultModel = new ErrorResultModel();
        }

        return resultModel;
    }


    @MethodChinaName(cname = "签收")
    @RouteCustomMenu(routeType = {RouteToType.SignReceive})
    @RequestMapping(method = RequestMethod.POST, value = "SignReceive")
    @APIEventAnnotation(callback = CustomCallBack.Reload, customRequestData = RequestPathEnum.ctx)
    public @ResponseBody
    ResultModel<Boolean> signReceive(String activityInstId) {
        ResultModel resultModel = new ResultModel();
        try {
            this.getClient().signReceive(activityInstId, null);
        } catch (BPMException e) {
            resultModel = new ErrorResultModel();
        }
        return resultModel;
    }

    @MethodChinaName(cname = "阅毕")
    @RequestMapping(method = RequestMethod.POST, value = "EndRead")
    @RouteCustomMenu(routeType = {RouteToType.EndRead})
    @APIEventAnnotation(callback = CustomCallBack.Close, customRequestData = RequestPathEnum.ctx)
    public @ResponseBody
    ResultModel<Boolean> endRead(String activityInstId) {
        ResultModel resultModel = new ResultModel();
        try {
            this.getClient().endRead(activityInstId, null);
        } catch (BPMException e) {
            resultModel = new ErrorResultModel();
        }
        return resultModel;
    }


    @MethodChinaName(cname = "自动推进")
    @RequestMapping(method = RequestMethod.POST, value = "AutoNext")
    @RouteCustomMenu(routeType = {RouteToType.AutoNext})
    @APIEventAnnotation(callback = CustomCallBack.DynReload, customRequestData = RequestPathEnum.ctx)
    public @ResponseBody
    ResultModel<String> autoNext(String activityInstId, String processInstId, String nextActivityDefId) {
        ResultModel<String> resultModel = new ResultModel();
        List<String> activityDefIds = new ArrayList<String>();
        List<Map<RightCtx, Object>> ctxs = new ArrayList<Map<RightCtx, Object>>();
        activityDefIds.add(nextActivityDefId);
        Map<RightCtx, Object> ctx = new HashMap<>();
        List<String> performList = new ArrayList<>();
        performList.add(this.getClient().getConnectInfo().getUserID());
        ctx.put(RightCtx.PERFORMERS, performList);
        ctxs.add(ctx);
        try {
            this.getClient().routeTo(activityInstId, activityDefIds, ctxs);
        } catch (BPMException e) {
            e.printStackTrace();
        }
        return resultModel;
    }

    @MethodChinaName(cname = "并行发送")
    @RequestMapping(method = RequestMethod.POST, value = "MultiRouteto")
    @RouteCustomMenu(routeType = {RouteToType.Multirouteto})
    @APIEventAnnotation(bindMenu = {CustomMenuItem.save}, isAllform = true, callback = {CustomCallBack.CloseParent, CustomCallBack.Close})
    public @ResponseBody
    ResultModel<Boolean> multiRouteto(@RequestBody RouteToBean routeToBean) {
        ResultModel resultModel = new ResultModel();
        resultModel.setData(false);
        String activityInstId = routeToBean.getActivityInstId();
        try {
            List<String> activityDefIds = new ArrayList<String>();
            Map<String, PerformBean> routeBeans = routeToBean.getMultiSelect();
            List<Map<RightCtx, Object>> ctxs = new ArrayList<Map<RightCtx, Object>>();
            Set<String> keySet = routeBeans.keySet();

            for (String nextActivityDefId : keySet) {
                RouteBean routeBean = routeBeans.get(nextActivityDefId).getPerformSelect();
                routeBean.setNextActivityDefId(nextActivityDefId);
                routeBean.setActivityInstId(routeToBean.getActivityInstId());
                routeBean.setAction(routeToBean.getAction());
                activityDefIds.add(routeBean.getNextActivityDefId());
                Map<RightCtx, Object> ctx = this.fillCtx(routeBean);
                ctxs.add(ctx);
            }

            getClient().routeTo(activityInstId, activityDefIds, ctxs);
            ActivityInst activityInst = this.getClient().getActivityInst(activityInstId);
            ActivityDefRight right = activityInst.getActivityDef().getRightAttribute();

//                // 当设定条件为单人办理且类型为自动签收时自动进入连续办理界面
            if (right.getPerformSequence().equals(ActivityDefPerformSequence.AUTOSIGN) && activityInst.isCanSignReceive() && right.getPerformType().equals(ActivityDefPerformtype.SINGLE)) {
                resultModel.setData(true);
            }


        } catch (BPMException e) {
            resultModel = new ErrorResultModel();
        }
        return resultModel;
    }


    @MethodChinaName(cname = "发送")
    @RequestMapping(method = RequestMethod.POST, value = "RouteTo")
    @RouteCustomMenu(routeType = {RouteToType.RouteTo})
    @APIEventAnnotation(bindMenu = {CustomMenuItem.save}, isAllform = true, callback = {CustomCallBack.CloseParent, CustomCallBack.Close})
    public @ResponseBody
    ResultModel<Boolean> routeTo(@RequestBody WebPerformPerson webPerformPerson) {

        RouteBean routeBean = new RouteBean();
        routeBean.setActivityInstId(webPerformPerson.getActivityInstId());
        routeBean.setAction(webPerformPerson.getAction());
        routeBean.setReaders(webPerformPerson.getSelectPerson().getReaders());
        routeBean.setPerforms(webPerformPerson.getSelectPerson().getPerforms());
        routeBean.setInsteadSigns(webPerformPerson.getSelectPerson().getInsteadSigns());
        routeBean.setActivityInstHistoryId(webPerformPerson.getActivityInstHistoryId());
        routeBean.setNextActivityDefId(webPerformPerson.getNextActivityDefId());
        routeBean.setInsteadSigns(webPerformPerson.getSelectPerson().getInsteadSigns());
        ResultModel resultModel = new ResultModel();
        resultModel.setData(false);
        String activityInstId = routeBean.getActivityInstId();
        try {
            List<String> activityDefIds = new ArrayList<String>();
            List<Map<RightCtx, Object>> ctxs = new ArrayList<Map<RightCtx, Object>>();
            activityDefIds.add(routeBean.getNextActivityDefId());
            Map<RightCtx, Object> ctx = this.fillCtx(routeBean);
            ctxs.add(ctx);
            getClient().routeTo(activityInstId, activityDefIds, ctxs);
            ActivityInst activityInst = this.getClient().getActivityInst(activityInstId);
            ActivityDefRight right = activityInst.getActivityDef().getRightAttribute();

//                // 当设定条件为单人办理且类型为自动签收时自动进入连续办理界面
            if (right.getPerformSequence().equals(ActivityDefPerformSequence.AUTOSIGN) && activityInst.isCanSignReceive() && right.getPerformType().equals(ActivityDefPerformtype.SINGLE)) {
                resultModel.setData(true);
            }


        } catch (BPMException e) {
            resultModel = new ErrorResultModel();
        }
        return resultModel;
    }


    @MethodChinaName(cname = "保存")
    @RequestMapping(method = RequestMethod.POST, value = "SaveOnly")
    @RouteCustomMenu(routeType = {RouteToType.SaveOnly})
    @APIEventAnnotation(isAllform = true, customRequestData = {RequestPathEnum.form, RequestPathEnum.ctx})
    public @ResponseBody
    ResultModel<Boolean> saveOnly(@RequestBody FormData data) {
        ResultModel resultModel = new ResultModel();
        try {
            ActivityInst inst = this.getClient().getActivityInst(data.getActivityInstId());
            DataMap map = inst.getFormValues();
            Map<String, DataMap> dataMap = data.getTable();
            map.putAll(dataMap);
            inst.updateFormValues(map);
        } catch (BPMException e) {
            e.printStackTrace();
        }


        return resultModel;
    }

    @MethodChinaName(cname = "结束")
    @RequestMapping(method = RequestMethod.POST, value = "RouteToEnd")
    @RouteCustomMenu(routeType = {RouteToType.RouteToEnd})
    @APIEventAnnotation(callback = CustomCallBack.Close, customRequestData = RequestPathEnum.ctx)
    public @ResponseBody
    ResultModel<Boolean> routeToEnd(String processInstId) {
        ResultModel resultModel = new ResultModel();
        try {
            this.getClient().completeProcessInst(processInstId, null);
        } catch (BPMException e) {
            resultModel = new ErrorResultModel();
        }
        return resultModel;

    }

    @MethodChinaName(cname = "查看历程")
    @RequestMapping(method = RequestMethod.POST, value = "ProcessView")
    @DynLoadAnnotation()
    @ModuleAnnotation(caption = "查看历程")
    @RouteCustomMenu(routeType = {RouteToType.View})
    @ResponseBody
    public ResultModel<SVGProcessInstView> processView(String activityInstId, String nextActivityDefId) {
        ResultModel<SVGProcessInstView> resultModel = new ResultModel<SVGProcessInstView>();
        return resultModel;

    }

    private Map<RightCtx, Object> fillCtx(RouteBean routeBean) throws BPMException {
        Map<RightCtx, Object> ctx = new HashMap<RightCtx, Object>();
        ActivityDef activityDef = getClient().getActivityDef(routeBean.getNextActivityDefId());
        // 办理类型
        ActivityDefPerformtype performType = activityDef.getRightAttribute().getPerformType();
        ActivityDefPerformSequence performSequence = activityDef.getRightAttribute().getPerformSequence();
        if (performType.equals(ActivityDefPerformtype.NOSELECT) || performType.equals(ActivityDefPerformtype.NEEDNOTSELECT)) {
            List<String> readList = new ArrayList<String>();
            List<String> performList = new ArrayList<String>();
            List<Person> persons = activityDef.getRightAttribute().getPerFormPersons();
            for (Person person : persons) {
                performList.add(person.getID());
            }
            List<Person> readpersons = activityDef.getRightAttribute().getReaderPersons();
            for (Person person : readpersons) {
                readList.add(person.getID());
            }
            ctx.put(RightCtx.PERFORMERS, performList);
            ctx.put(RightCtx.READERS, readList);
        } else {
            String[] performArr = StringUtility.split(routeBean.getPerforms().getPerforms(), ";");
            String[] readArr = StringUtility.split(routeBean.getReaders().getReaders(), ";");
            List<String> performList = Arrays.asList(performArr);
            ctx.put(RightCtx.PERFORMERS, performList);
            ctx.put(RightCtx.READERS, Arrays.asList(readArr));

        }
        return ctx;
    }


    /**
     * @return
     */
    private WorkflowClientService getClient() {

        WorkflowClientService client = ((WorkflowClientService) EsbUtil.parExpression("$BPMC"));

        return client;
    }
}
